package main

import (
	"fmt"
	"reflect"
)

/*
1、reflect.Value.Kind，获取变量的类别，返回的是一个常量
2、Type是类型，Kind是类别，Type和Kind可能是相同的，也可能是不同的
比如：var num int = 10 num的Type是int，Kind也是int
比如：var stu Student stu的Type是包名.Student，Kind是struct
3、通过反射可以让变量在interface{}和refle.Value之间相互转换
变量<--->interface{}<--->reflect.Value
4、使用反射的方式来获取变量的值（并返回对应的类型），要求数据类型匹配，比如x是int，那么就应该使用reflect.Value(x).Int()，而不能使用其它的，否则报panic
5、通过反射来修改变量，注意当使用SetXxx方法来设置需要通过对应的指针类型来完成，这样才能改变传入变量的值，同时需要使用到reflect.Value.Elem()方法

*/
//通过反射，修改
//num int的值
//修改
func reflectTest02(b interface{}) {
	//获取到reflect.Value
	rVal := reflect.ValueOf(b)
	//看看rVal的Kind是
	fmt.Printf("rVal kind=%v\n", rVal.Kind())
	//func (v Value) Elem() Value
	//Elem返回v持有的接口保管的值的Value封装，或者v持有的指针指向的值的Value封装。如果v的Kind不是Interface或Ptr会panic；如果v持有的值为nil，会返回Value零值。
	//func (v Value) SetInt(x int64)
	//设置v的持有值。如果v的Kind不是Int、Int8、Int16、Int32、Int64之一或者v.CanSet()返回假，会panic。
	rVal.Elem().SetInt(20)
}
func reflectTest01(b interface{}) {
	rTyp := reflect.TypeOf(b)
	rVal := reflect.ValueOf(b)
	//获取变量对应的kind
	kind1 := rTyp.Kind()
	kind2 := rVal.Kind()
	fmt.Printf("kind1=%v kind2=%v", kind1, kind2)
}
func main() {
	//1
	var num int = 10
	reflectTest01(num)

	//5
	reflectTest02(&num)
	fmt.Println("num=", num)

}
